﻿using System;
using System.Collections.Generic;
using Infraestrutura.Repositorios.SQL;
using System.Configuration;
using System.Data.SqlClient;
using Model.Tipologias;
using Model.Contratos;
using Model.Clientes;
using System.Globalization;
using Model.Refeicoes;

namespace Repository.SQL.Refeicoes
{
    public class RefeicaoRepository: RepositorioSQL<Refeicao>, IRefeicaoRepository
    {
        public RefeicaoRepository()
        {
            Tabela = "Refeicoes";
            LigacaoBD = ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
        }


        #region Refeições

        public Refeicao ObterPorRefeicaoContratadaData(Int64 idRefeicaoContratada, DateTime dataRefeicao)
        {
            return ObterPorChave(String.Format("@idRefeicaoContratada={0}, @DataRefeicao='{1}'",
                                                  idRefeicaoContratada, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")));
        }

        public IList<Refeicao> ObterPorUnidadeData(Int64 idUnidade, DateTime dataRefeicao)
        {
            return ObterLista(String.Format("proc_RefeicoesLoadByUnidadeData @IdUnidade={0}, @DataRefeicao='{1}'",
                                               idUnidade, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")));
        }

        public IList<Refeicao> ObterRefeicaoPorContratoDataRefeicao(Int64 numeroContrato, DateTime dataRefeicao)
        {
            return ObterLista(String.Format("proc_RefeicoesContratadasLoadByDataRefeicao @NumeroContrato={0}, @DataRefeicao='{1}'",
                                               numeroContrato, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")));
        }

        public IList<Refeicao> ObterTodasContratadasPorUnidadeData(Int64 idUnidade, DateTime dataRefeicao)
        {
            return ObterLista(String.Format("proc_RefeicoesLoadTodasContratoByUnidadeData @IdUnidade={0}, @DataRefeicao='{1}'",
                                              idUnidade, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")));
        }

        public IList<Refeicao> ObterRefeicaoPorEstado(String estado)
        {
            return ObterLista(String.Format("exec proc_RefeicaoLoadByEstado @CodEstadoRefeicao={0}", estado));
        }

        public override IList<Refeicao> Insere(IList<Refeicao> items)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                connection.Open();
                SqlTransaction transaction = connection.BeginTransaction();

                SqlCommand command = null;
                foreach (Refeicao item in items)
                {
                    command = new SqlCommand(
                        String.Format("exec proc_{0}Insert {1}", Tabela, ObterParametrosInserir(item)),
                        connection, transaction);

                    item.AtribuirChave(command.ExecuteScalar());

                    foreach (RefeicaoOpcao ro in item.OpcoesRefeicao)
                    {
                        Insere(ro, transaction);
                    }

                    foreach (RefeicaoUnidade ru in item.UnidadeRefeicao)
                    {
                        Insere(ru, transaction);
                    }
                }
                transaction.Commit();
            }

            return items;
        }

        protected override Refeicao CarregarDados(System.Data.SqlClient.SqlDataReader dataReader, Refeicao item)
        {
            item.CodEstadoRefeicao = dataReader["CodEstadoRefeicao"].ToString();
            if (!Convert.IsDBNull(dataReader["NumeroRequisicao"]))
                item.NumeroRequisicao = Convert.ToInt64(dataReader["NumeroRequisicao"]);
            if (!Convert.IsDBNull(dataReader["DataRefeicao"]))
                item.DataRefeicao = Convert.ToDateTime(dataReader["DataRefeicao"]);
            if (!Convert.IsDBNull(dataReader["RacioMPrimasEfectivo"]))
                item.RacioMateriasPrimasEfectivo = Convert.ToDecimal(dataReader["RacioMPrimasEfectivo"]);
            if (!Convert.IsDBNull(dataReader["RacioMPrimasPrevisto"]))
                item.RacioMateriasPrimasPrevisto = Convert.ToDecimal(dataReader["RacioMPrimasPrevisto"]);
            if (!Convert.IsDBNull(dataReader["TotalCustosEfectivo"]))
                item.TotalCustosEfectivo = Convert.ToDecimal(dataReader["TotalCustosEfectivo"]);
            if (!Convert.IsDBNull(dataReader["TotalCustosPrevisto"]))
                item.TotalCustosPrevisto = Convert.ToDecimal(dataReader["TotalCustosPrevisto"]);
            if (!Convert.IsDBNull(dataReader["TotalVendasEfectivo"]))
                item.TotalVendasEfectivo = Convert.ToDecimal(dataReader["TotalVendasEfectivo"]);
            if (!Convert.IsDBNull(dataReader["TotalVendasPrevisto"]))
                item.TotalVendasPrevisto = Convert.ToDecimal(dataReader["TotalVendasPrevisto"]);

            item.RefeicaoContratada = new RefeicaoContrato();
            item.RefeicaoContratada.IdRefeicaoContratada = Convert.ToInt64(dataReader["IdRefeicaoContratada"]);
            item.RefeicaoContratada.Contrato = new Contrato();
            item.RefeicaoContratada.Contrato.NumeroContrato = Convert.ToInt64(dataReader["NumeroContrato"]);
            item.RefeicaoContratada.Contrato.DataContrato = Convert.ToDateTime(dataReader["DataContrato"]);
            item.RefeicaoContratada.Contrato.DataInicioContrato = Convert.ToDateTime(dataReader["DataInicioContrato"]);
            item.RefeicaoContratada.Contrato.DataFimContrato = Convert.ToDateTime(dataReader["DataFimContrato"]);
            item.RefeicaoContratada.Contrato.Cliente = new Cliente()
            {
                IdCliente = Convert.ToInt64(dataReader["IdCliente"]),
                Nome = dataReader["Nome"].ToString()
            };
            item.RefeicaoContratada.Contrato.Unidade = new Unidade();
            item.RefeicaoContratada.Contrato.Unidade.IdUnidade = Convert.ToInt64(dataReader["IdUnidade"]);
            item.RefeicaoContratada.Contrato.Unidade.Designacao = dataReader["Designacao"].ToString();
            item.RefeicaoContratada.Contrato.Unidade.Servico = Convert.ToBoolean(dataReader["Servico"]);
            item.RefeicaoContratada.Contrato.Cliente = item.RefeicaoContratada.Contrato.Cliente;
            if (!Convert.IsDBNull(dataReader["UnidadePai"]))
                item.RefeicaoContratada.Contrato.Unidade.UnidadePai = new Unidade() { IdUnidade = Convert.ToInt64(dataReader["Servico"]) };

            item.RefeicaoContratada.TipoRefeicao = new Tipologia();
            item.RefeicaoContratada.TipoRefeicao.Codigo = dataReader["CodTipoRefeicao"].ToString();
            item.RefeicaoContratada.TipoRefeicao.Descricao = dataReader["DescricaoTipoRefeicao"].ToString();
            item.RefeicaoContratada.TipoRefeicao.DescricaoCurta = dataReader["DescricaoCurtaTipoRefeicao"].ToString();
            item.RefeicaoContratada.TipoRefeicao.Simbolo = dataReader["SimboloTipoRefeicao"].ToString();

            if (!Convert.IsDBNull(dataReader["CodTipoClasseRefeitorio"]))
            {
                item.RefeicaoContratada.TipoClasseRefeicao = new Tipologia();
                item.RefeicaoContratada.TipoClasseRefeicao.Codigo = dataReader["CodTipoClasseRefeitorio"].ToString();
                item.RefeicaoContratada.TipoClasseRefeicao.Descricao = dataReader["DescricaoClasseRefeicao"].ToString();
                item.RefeicaoContratada.TipoClasseRefeicao.DescricaoCurta = dataReader["DescricaoCurtaClasseRefeicao"].ToString();
                item.RefeicaoContratada.TipoClasseRefeicao.Simbolo = dataReader["SimboloClasseRefeicao"].ToString();
            }

            //TODO: Falta carregar item.OpcoesRefeicao

            return item;
        }

        protected override string ObterParametrosInserir(Refeicao item)
        {

            String strCommand = String.Format("@IdRefeicaoContratada={0}, @DataRefeicao='{1}', @CodEstadoRefeicao='{2}'",
                                  item.RefeicaoContratada.IdRefeicaoContratada,
                                  item.DataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss"),
                                  item.CodEstadoRefeicao);

            if (item.TotalVendasPrevisto.HasValue)
                strCommand = String.Concat(strCommand, String.Format(", @TotalVendasPrevisto={0}", item.TotalVendasPrevisto.Value.ToString(NumberFormatInfo.InvariantInfo)));
            if (item.TotalCustosPrevisto.HasValue)
                strCommand = String.Concat(strCommand, String.Format(", @TotalCustosPrevisto={0}", item.TotalCustosPrevisto.Value.ToString(NumberFormatInfo.InvariantInfo)));
            if (item.TotalVendasEfectivo.HasValue)
                strCommand = String.Concat(strCommand, String.Format(", @TotalVendasEfectivo={0}", item.TotalVendasEfectivo.Value.ToString(NumberFormatInfo.InvariantInfo)));
            if (item.TotalCustosEfectivo.HasValue)
                strCommand = String.Concat(strCommand, String.Format(", @TotalCustosEfectivo={0}", item.TotalCustosEfectivo.Value.ToString(NumberFormatInfo.InvariantInfo)));
            if (item.RacioMateriasPrimasPrevisto.HasValue)
                strCommand = String.Concat(strCommand, String.Format(", @RacioMPrimasPrevisto={0}", item.RacioMateriasPrimasPrevisto.Value.ToString(NumberFormatInfo.InvariantInfo)));
            if (item.RacioMateriasPrimasEfectivo.HasValue)
                strCommand = String.Concat(strCommand, String.Format(", @RacioMPrimasEfectivo={0}", item.RacioMateriasPrimasEfectivo.Value.ToString(NumberFormatInfo.InvariantInfo)));
            if(item.NumeroRequisicao.HasValue)
                strCommand = String.Concat(strCommand, String.Format(", @NumeroRequisicao={0}", item.NumeroRequisicao.Value.ToString()));

            return strCommand;
            
        }

        protected override string ObterParametrosApagar(Refeicao item)
        {
            return String.Format("@IdRefeicaoContratada={0}, @DataRefeicao='{1}'",
                                  item.RefeicaoContratada.IdRefeicaoContratada,
                                  item.DataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss"));
        }

        #endregion

        #region RefeicaoOpcao

        public RefeicaoOpcao ObterRefeicaoOpcaoPorChaveRefeicaoOpcao(Int64 idRefeicaoContratada, DateTime dataRefeicao, String codOpcao)
        {
            RefeicaoOpcao item = null;

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_OpcoesRefeicoesLoadByPrimaryKey @IdRefeicaoContratada={0}, @DataRefeicao='{1}', @CodOpcao='{2}'",
                                 idRefeicaoContratada, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss"), codOpcao),
                  sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                if (reader.Read())
                {
                    item = new RefeicaoOpcao();
                    item = CarregarDados(reader, item);
                }

                reader.Close();
            }

            return item;
        }


        public IList<RefeicaoOpcao> ObterTodosRefeicaoOpcaoPorRefeicao(Int64 idRefeicaoContratada, DateTime dataRefeicao)
        {
            IList<RefeicaoOpcao> lista = new List<RefeicaoOpcao>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_OpcoesRefeicoesLoadByRefeicao @IdRefeicaoContratada={0}, @DataRefeicao='{1}'",
                                 idRefeicaoContratada, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")),
                                 sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                RefeicaoOpcao item = null;
                Refeicao refeicao = null;
                while (reader.Read())
                {
                    item = new RefeicaoOpcao();

                    if (refeicao != null)
                    {
                        lista.Add(CarregarDados(reader, item, refeicao));
                    }
                    else
                    {
                        lista.Add(CarregarDados(reader, item));
                        refeicao = item.Refeicao;
                    }

                }

                reader.Close();
            }

            return lista;
        }


        public IList<RefeicaoOpcao> ObterTodosRefeicaoOpcaoPorRefeicao(Refeicao refeicao)
        {
            IList<RefeicaoOpcao> lista = new List<RefeicaoOpcao>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_OpcoesRefeicoesLoadByRefeicao @IdRefeicaoContratada={0}, @DataRefeicao='{1}'",
                                 refeicao.RefeicaoContratada.IdRefeicaoContratada, 
                                 refeicao.DataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")),
                                 sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                RefeicaoOpcao item = null;
                
                while (reader.Read())
                {
                    item = new RefeicaoOpcao();
                    lista.Add(CarregarDados(reader, item, refeicao));
                }

                reader.Close();
            }

            return lista;
        }


        public RefeicaoOpcao Actualiza(RefeicaoOpcao item)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_OpcoesRefeicoesUpdate {0}", ObterParametrosActualizar(item)),
                    connection);

                command.Connection.Open();
                command.ExecuteScalar();
            }

            return item;
        }

        public IList<RefeicaoOpcao> Actualiza(IList<RefeicaoOpcao> items)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                connection.Open();
                SqlTransaction transaction = connection.BeginTransaction();

                SqlCommand command = null;
                foreach (RefeicaoOpcao item in items)
                {
                    command = new SqlCommand(
                        String.Format("exec proc_OpcoesRefeicoesUpdate {0}", ObterParametrosInserir(item)),
                        connection, transaction);

                    item.AtribuirChave(command.ExecuteScalar());
                }
                transaction.Commit();
            }

            return items;
        }

        public RefeicaoOpcao Insere(RefeicaoOpcao item)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_OpcoesRefeicoesInsert {0}", ObterParametrosInserir(item)),
                    connection);

                command.Connection.Open();
                item.AtribuirChave(command.ExecuteScalar());
            }

            return item;
        }

        private RefeicaoOpcao Insere(RefeicaoOpcao item, SqlTransaction transaction)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_OpcoesRefeicoesInsert {0}", ObterParametrosInserir(item)),
                    transaction.Connection, transaction);

                item.AtribuirChave(command.ExecuteScalar());
            }

            return item;
        }

        public void Apaga(RefeicaoOpcao item)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_OpcoesRefeicoesDelete {0}", ObterParametrosApagar(item)),
                    connection);

                command.Connection.Open();
                command.ExecuteNonQuery();
            }
        }

        protected String ObterParametrosActualizar(RefeicaoOpcao item)
        {
            return ObterParametrosInserir(item);
        }

        protected String ObterParametrosInserir(RefeicaoOpcao item)
        {
            return String.Format("@IdRefeicaoContratada={0}, @DataRefeicao='{1}', @CodOpcao='{2}', @Descricao='{3}' ",
                                      item.Refeicao.RefeicaoContratada.IdRefeicaoContratada,
                                      item.Refeicao.DataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss"),
                                      item.TipoOpcao.Codigo,
                                      item.Descricao);
        }
        
        protected String ObterParametrosApagar(RefeicaoOpcao item)
        {
            return String.Format("@IdRefeicaoContratada={0}, @DataRefeicao='{1}', @CodOpcao='{2}'",
                                  item.Refeicao.RefeicaoContratada.IdRefeicaoContratada,
                                  item.Refeicao.DataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss"), 
                                  item.TipoOpcao.Codigo);
        }


        private RefeicaoOpcao CarregarDados(SqlDataReader dataReader, RefeicaoOpcao item)
        {
            return CarregarDados(dataReader, item,
                        ObterPorRefeicaoContratadaData(Convert.ToInt64(dataReader["IdRefeicaoContratada"]), Convert.ToDateTime(dataReader["DataRefeicao"])));
        }

        private RefeicaoOpcao CarregarDados(SqlDataReader dataReader, RefeicaoOpcao item, Refeicao refeicao)
        {
            item.Descricao = dataReader["Descricao"].ToString();
            item.Refeicao = refeicao;
            item.TipoOpcao = new Tipologia();
            item.TipoOpcao.Tipo = dataReader["TipoOpcao"].ToString();
            item.TipoOpcao.Codigo = dataReader["CodOpcao"].ToString();
            item.TipoOpcao.Descricao = dataReader["DescricaoOpcao"].ToString();
            item.TipoOpcao.DescricaoCurta = dataReader["DescricaoCurtaOpcao"].ToString();
            item.TipoOpcao.Simbolo = dataReader["SimboloOpcao"].ToString();

            return item;
        }

        #endregion

        #region RefeicaoUnidade

        public RefeicaoUnidade ObterRefeicaoUnidadePorChaveRefeicaoUnidade(Int64 idRefeicaoContratada, DateTime dataRefeicao, Int64 idUnidade)
        {
            RefeicaoUnidade item = null;

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RefeicaoUnidadeLoadByPrimaryKey @IdRefeicaoContratada={0}, @DataRefeicao='{1}', @IdUnidade='{3}'",
                                 idRefeicaoContratada, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss"), idUnidade),
                  sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                if (reader.Read())
                {
                    item = new RefeicaoUnidade();
                    item = CarregarDados(reader, item);
                }

                reader.Close();
            }

            return item;
        }

        public IList<RefeicaoUnidade> ObterTodosRefeicaoUnidadePorRefeicao(Int64 idRefeicaoContratada, DateTime dataRefeicao)
        {
            IList<RefeicaoUnidade> lista = new List<RefeicaoUnidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RefeicaoUnidadeLoadByRefeicao @IdRefeicaoContratada={0}, @DataRefeicao='{1}'",
                                 idRefeicaoContratada, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")),
                                 sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                RefeicaoUnidade item = null;
                Refeicao refeicao = null;
                while (reader.Read())
                {
                    item = new RefeicaoUnidade();

                    if (refeicao != null)
                    {
                        lista.Add(CarregarDados(reader, item, refeicao));
                    }
                    else
                    {
                        lista.Add(CarregarDados(reader, item));
                        refeicao = item.Refeicao;
                    }

                }

                reader.Close();
            }

            return lista;
        }

        public IList<RefeicaoUnidade> ObterTodosRefeicaoUnidadePorUnidadeDataRefeicao(Int64 idUnidade, DateTime dataRefeicao)
        {
            IList<RefeicaoUnidade> lista = new List<RefeicaoUnidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RefeicaoUnidadeLoadByUnidadeDataRefeicao @IdUnidade={0}, @DataRefeicao='{1}'",
                                 idUnidade, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")),
                                 sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();
                RefeicaoUnidade item = null;
                
                while (reader.Read())
                {
                    item = new RefeicaoUnidade();
                    lista.Add(CarregarDados(reader, item));
                }

                reader.Close();
            }

            return lista;
        }

        public IList<RefeicaoUnidade> ObterTodosRefeicaoUnidadeContratadasPorDataRefeicao(Int64 numeroContrato, DateTime dataRefeicao)
        {
            IList<RefeicaoUnidade> lista = new List<RefeicaoUnidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RefeicaoUnidadeLoadByNumerocontrato @IdUnidade={0}, @DataRefeicao='{1}'",
                                 numeroContrato, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")),
                                 sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();
                RefeicaoUnidade item = null;

                while (reader.Read())
                {
                    item = new RefeicaoUnidade();
                    lista.Add(CarregarDados(reader, item));
                }

                reader.Close();
            }

            return lista;
        }

        public IList<RefeicaoUnidade> ObterTodosRefeicaoUnidadeContratadasPorRefeicao(Refeicao refeicao)
        {

            IList<RefeicaoUnidade> lista = new List<RefeicaoUnidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RefeicaoUnidadeLoadTodasContratoByRefeicao @IdRefeicaoContratada={0}, @DataRefeicao='{1}'",
                                 refeicao.RefeicaoContratada.IdRefeicaoContratada, refeicao.DataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")),
                                 sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                RefeicaoUnidade item = null;
               
                while (reader.Read())
                {
                    item = new RefeicaoUnidade();

                    lista.Add(CarregarDados(reader, item, refeicao));
                }

                reader.Close();
            }

            return lista;
        }

        public IList<RefeicaoUnidade> ObterTodosRefeicaoUnidadeContratadasPorRefeicao(Int64 idRefeicaoContratada, DateTime dataRefeicao)
        {
            IList<RefeicaoUnidade> lista = new List<RefeicaoUnidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RefeicaoUnidadeLoadTodasContratoByRefeicao @IdRefeicaoContratada={0}, @DataRefeicao='{1}'",
                                 idRefeicaoContratada, dataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")),
                                 sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                RefeicaoUnidade item = null;
                Refeicao refeicao =  ObterPorRefeicaoContratadaData(idRefeicaoContratada, dataRefeicao);
                while (reader.Read())
                {
                    item = new RefeicaoUnidade();

                    lista.Add(CarregarDados(reader, item, refeicao));
                }

                reader.Close();
            }

            return lista;
        }
               
        public IList<RefeicaoUnidade> ObterTodosRefeicaoUnidadePorRefeicao(Refeicao refeicao)
        {
            IList<RefeicaoUnidade> lista = new List<RefeicaoUnidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RefeicaoUnidadeLoadByRefeicao @IdRefeicaoContratada={0}, @DataRefeicao='{1}'",
                                 refeicao.RefeicaoContratada.IdRefeicaoContratada,
                                 refeicao.DataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss")),
                                 sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                RefeicaoUnidade item = null;

                while (reader.Read())
                {
                    item = new RefeicaoUnidade();
                    lista.Add(CarregarDados(reader, item, refeicao));
                }

                reader.Close();
            }

            return lista;
        }

        public IList<RefeicaoUnidade> ObterTodosRefeicaoUnidadeAguradaNumRefeicoesServidas()
        {
             IList<RefeicaoUnidade> lista = new List<RefeicaoUnidade>();

            using (SqlConnection sqlConnection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                  String.Format("exec proc_RefeicaoUnidadeLoadByAguardaServidas"),
                                 sqlConnection);

                sqlConnection.Open();

                SqlDataReader reader = command.ExecuteReader();

                RefeicaoUnidade item = null;

                while (reader.Read())
                {
                    item = new RefeicaoUnidade();
                    lista.Add(CarregarDados(reader, item));
                }

                reader.Close();
            }

            return lista;
        }

        public RefeicaoUnidade Actualiza(RefeicaoUnidade item)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_RefeicaoUnidadeUpdate {0}", ObterParametrosActualizar(item)),
                    connection);

                command.Connection.Open();
                command.ExecuteScalar();
            }

            return item;
        }

        public IList<RefeicaoUnidade> Actualiza(IList<RefeicaoUnidade> items)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                connection.Open();
                SqlTransaction transaction = connection.BeginTransaction();

                SqlCommand command = null;
                foreach (RefeicaoUnidade item in items)
                {
                    command = new SqlCommand(
                        String.Format("exec proc_RefeicaoUnidadeUpdate {0}", ObterParametrosInserir(item)),
                        connection, transaction);

                    item.AtribuirChave(command.ExecuteScalar());
                }
                transaction.Commit();
            }

            return items;
        }

        public RefeicaoUnidade Insere(RefeicaoUnidade item)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_RefeicaoUnidadeInsert {0}", ObterParametrosInserir(item)),
                    connection);

                command.Connection.Open();
                item.AtribuirChave(command.ExecuteScalar());
            }

            return item;
        }

        private RefeicaoUnidade Insere(RefeicaoUnidade item, SqlTransaction transaction)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_RefeicaoUnidadeInsert {0}", ObterParametrosInserir(item)),
                    transaction.Connection, transaction);

                item.AtribuirChave(command.ExecuteScalar());
            }

            return item;
        }

        public void Apaga(RefeicaoUnidade item)
        {
            using (SqlConnection connection = new SqlConnection(LigacaoBD))
            {
                SqlCommand command = new SqlCommand(
                    String.Format("exec proc_RefeicaoUnidadeDelete {0}", ObterParametrosApagar(item)),
                    connection);

                command.Connection.Open();
                command.ExecuteNonQuery();
            }
        }

        protected String ObterParametrosApagar(RefeicaoUnidade item)
        {
            return String.Format("@IdRefeicaoContratada={0}, @DataRefeicao='{1}' @IdUnidade={2}",
                                  item.Refeicao.RefeicaoContratada.IdRefeicaoContratada,
                                  item.Refeicao.DataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss"),
                                  item.Unidade.IdUnidade);
        }

        protected String ObterParametrosActualizar(RefeicaoUnidade item)
        {
            return ObterParametrosInserir(item);
        }

        protected String ObterParametrosInserir(RefeicaoUnidade item)
        {
            String sqlCommandText = String.Format("@IdRefeicaoContratada={0}, @DataRefeicao='{1}', @IdUnidade={2}, @CodTipoServico='{3}', @DescricaoTipoServico='{4}'",
                                      item.Refeicao.RefeicaoContratada.IdRefeicaoContratada,
                                      item.Refeicao.DataRefeicao.ToString("yyyy-MM-ddTHH:mm:ss"),
                                      item.Unidade.IdUnidade,
                                      item.CodTipoServico,
                                      item.DescricaoTipoServico);
                                      
            sqlCommandText = String.Concat(sqlCommandText, ", @PrecoRefeicao=", item.PrecoRefeicao.ToString(NumberFormatInfo.InvariantInfo));
            
            if(item.RefeicoesPrevistas.HasValue)
                sqlCommandText = String.Concat(sqlCommandText, ", @RefeicoesPrevistas=", item.RefeicoesPrevistas.Value.ToString(NumberFormatInfo.InvariantInfo));
            if (item.RefeicoesServidas.HasValue)
                sqlCommandText = String.Concat(sqlCommandText, ", @RefeicoesServidas=", item.RefeicoesServidas.Value.ToString(NumberFormatInfo.InvariantInfo));

            return sqlCommandText;
             
        }

        private RefeicaoUnidade CarregarDados(SqlDataReader dataReader, RefeicaoUnidade item)
        {
            return CarregarDados(dataReader, item,
                        ObterPorRefeicaoContratadaData(Convert.ToInt64(dataReader["IdRefeicaoContratada"]),
                                                       Convert.ToDateTime(dataReader["DataRefeicao"])));
        }

        private RefeicaoUnidade CarregarDados(SqlDataReader dataReader, RefeicaoUnidade item, Refeicao refeicao)
        {
            
            item.Refeicao = refeicao;
            item.CodTipoServico = dataReader["CodTipoServico"].ToString();
            item.DescricaoTipoServico = dataReader["DescricaoTipoServico"].ToString();
            if(!Convert.IsDBNull(dataReader["PrecoRefeicao"]))
                item.PrecoRefeicao = Convert.ToDecimal(dataReader["PrecoRefeicao"]);
            
            if (!Convert.IsDBNull(dataReader["RefeicoesPrevistas"]))
                item.RefeicoesPrevistas = Convert.ToDecimal(dataReader["RefeicoesPrevistas"]);
            if (!Convert.IsDBNull(dataReader["RefeicoesServidas"]))
                item.RefeicoesServidas = Convert.ToDecimal(dataReader["RefeicoesServidas"]);

            item.Unidade = new Unidade();
            item.Unidade.IdUnidade = Convert.ToInt64(dataReader["IdUnidade"]);
            item.Unidade.Cliente = refeicao.RefeicaoContratada.Contrato.Cliente;
            item.Unidade.Designacao = dataReader["Designacao"].ToString();
            item.Unidade.Servico = Convert.ToBoolean(dataReader["Servico"]);
            item.Unidade.UnidadePai = new Unidade() { IdUnidade = Convert.ToInt64(dataReader["UnidadePai"]) };


            return item;
        }

        #endregion
    }
}
